package im_server

import (
	"encoding/json"
	"errors"
	"fmt"
	"github.com/gomodule/redigo/redis"
	"go.uber.org/zap"
	"gorm.io/gorm"
	"gorm.io/gorm/clause"
	"pim/pkg/codes"
	"pim/pkg/models"
)

func (c *ClientConn) SenderMsgApi(req *models.SenderMsgReq) (resp *models.SenderMsgResp, err error) {

	msgID := c.GenMsgID()

	createAt := msgID.Time()

	paramJson, _ := json.Marshal(req.Params)
	atUserJson, _ := json.Marshal(req.AtUser)
	newMessageID := msgID.Int64()
	// 产生消息
	saveMsg := &models.SingleMessage{
		MsgID:            newMessageID,
		CreatedAt:        createAt,
		UpdatedAt:        createAt,
		Sender:           c.UserID,
		ChatID:           req.ChatID,
		MsgType:          req.MsgType,
		MsgStatus:        models.SenderMsgStateSend,
		Body:             req.Body,
		Attach:           req.Attach,
		Params:           paramJson,
		AtUser:           atUserJson,
		ReplyToMessageID: req.ReplyToMessageID,
		ReplyInChatID:    req.ReplyInChatID,
	}
	sendMsg := &models.SingleMessageDataType{
		MsgID:            newMessageID,
		CreatedAt:        createAt,
		UpdatedAt:        createAt,
		Sender:           c.UserID,
		ChatID:           req.ChatID,
		MsgType:          req.MsgType,
		MsgStatus:        models.SenderMsgStateSend,
		Body:             req.Body,
		Attach:           req.Attach,
		Params:           req.Params,
		AtUser:           req.AtUser,
		ReplyToMessageID: req.ReplyToMessageID,
		ReplyInChatID:    req.ReplyInChatID,
	}
	c.svr.saveMessageChan <- saveMsg

	c.svr.sendMessageChan <- sendMsg

	// 返回成功

	sendApiReq := &models.SenderMsgResp{
		MsgID: newMessageID,
	}

	return sendApiReq, nil
}

func (c *ClientConn) CreateChatApi(req *models.CreateChatReq) (resp *models.ChatInfoDataType, err error) {

	// 先从redis 判断是否存在这个会话

	if req.UserID <= 0 {
		err = errors.New("userid fail")
		return
	}

	redisConn := c.svr.redisPool.Get()
	defer redisConn.Close()

	rkey := fmt.Sprintf("%s:%X:%X", codes.RedisUserChatListPrefix, c.UserID, req.UserID)

	replyBytes, err := redis.Values(redisConn.Do("HGETALL", rkey))
	if err != nil {
		return
	}

	// 有数据库 这是一个json

	resp = new(models.ChatInfoDataType)

	err = redis.ScanStruct(replyBytes, resp)

	//err = json.Unmarshal(replyBytes, resp)
	if err == nil {
		// 判断是否为空
		if resp.ChatID != 0 {
			// 直接返回

			return
		}
	}

	// 不存在 则创建会话
	// TODO 查找用户信息 ， 后期该redis

	uinfo := models.UserInfoViewer{}

	db := c.svr.db

	if dbResp := db.Model(&uinfo).Where(&models.UserInfoViewer{UserID: req.UserID}).Find(&uinfo); dbResp.Error != nil || dbResp.RowsAffected == 0 {
		// 查询用户失败
		c.logger.Debug("查询用户失败", zap.Error(dbResp.Error))
		err = errors.New("用户信息不存在")
		return
	}

	itemChatInfoItem := &models.ChatInfoDataType{}
	itemChatInfoItem.MyUserID = c.UserID
	itemChatInfoItem.ChatID = req.UserID
	itemChatInfoItem.ChatName = uinfo.Nick
	if itemChatInfoItem.ChatTitle == "" {
		itemChatInfoItem.ChatName = fmt.Sprintf("p_%s", uinfo.Username)
	}
	if itemChatInfoItem.ChatTitle == "" {
		itemChatInfoItem.ChatName = fmt.Sprintf("pid_%d", uinfo.UserID)
	}

	// 插入数据库
	if dbResp := db.Clauses(&clause.OnConflict{
		DoNothing: false,
	}).Create(itemChatInfoItem); dbResp.Error != nil {
		// 创建会话失败
		err = errors.New("创建会话失败")
		return
	}

	// 创建成功 存redis

	_, err = redisConn.Do("HMSET", redis.Args{rkey}.AddFlat(itemChatInfoItem)...)
	if err != nil {
		// 保存redis 失败 ??? 处理
		c.logger.Debug("保存会话到redis 失败")
	}
	_, err = redisConn.Do("EXPIRE", rkey, 3600*24*7)

	resp = itemChatInfoItem
	err = nil
	return
}

func DBMessageToClientMessage(currentUserId int64, message *models.SingleMessage) *models.SingleMessageDataType {
	tmp := &models.SingleMessageDataType{}

	if message.ChatID < 0 {
		tmp.ChatID = message.ChatID
	} else {
		if message.ChatID == currentUserId {
			tmp.ChatID = message.Sender
		} else {
			tmp.ChatID = message.ChatID
		}
	}

	tmp.MsgID = message.MsgID
	tmp.CreatedAt = message.CreatedAt
	tmp.UpdatedAt = message.UpdatedAt
	tmp.Sender = message.Sender

	tmp.MsgType = message.MsgType
	tmp.MsgStatus = message.MsgStatus
	tmp.Body = message.Body
	tmp.Attach = message.Attach
	tmp.ReplyToMessageID = message.ReplyToMessageID
	tmp.ReplyInChatID = message.ReplyInChatID

	// 序列化 AtUser

	if message.AtUser != nil {
		tmpAtuserErr := json.Unmarshal(message.AtUser, &tmp.AtUser)
		//c.logger.Debug("json at user Unmarshal err", zap.Error(tmpAtuserErr))
		_ = tmpAtuserErr
	}

	if message.Params != nil {
		tmpParamsErr := json.Unmarshal(message.Params, &tmp.Params)
		_ = tmpParamsErr
		//c.logger.Debug("json Params Unmarshal err", zap.Error(tmpParamsErr))
	}

	return tmp
}

func (c *ClientConn) SyncChatMsgApi(req *models.SyncChatMsgReq) (resp *models.SyncChatMsgResp, err error) {
	// 查询数据库

	db := c.svr.db

	var pushList []*models.SingleMessage

	resp = new(models.SyncChatMsgResp)

	var dbResp *gorm.DB
	if req.ChatID < 0 {
		// 群组的处理方式 , 只看chat id 相同即可

		if req.Type > 0 {
			dbResp = db.Model(&models.SingleMessage{}).
				Where("msg_id > ?  and msg_id not in ? and   chat_id = ?  ",
					req.OldMsgID,
					req.Exclude,
					req.ChatID,
				).
				Find(&pushList)
		} else {

			dbResp = db.Model(&models.SingleMessage{}).
				Where("msg_id > ? and msg_id < ? and msg_id not in ? and   chat_id = ?  ",
					req.OldMsgID, req.LastMsgID, req.Exclude,
					//c.UserID , req.
					req.ChatID,
				).
				Find(&pushList)
		}
	} else {
		// 个人的处理方式
		if req.Type > 0 {
			dbResp = db.Model(&models.SingleMessage{}).
				Where("msg_id > ?   and msg_id not in ? and ( (chat_id = ? and sender = ? ) or (chat_id = ? and sender = ? ))",
					req.OldMsgID, req.Exclude,
					c.UserID, req.ChatID, req.ChatID, c.UserID,
				).
				Find(&pushList)
		} else {

			dbResp = db.Model(&models.SingleMessage{}).
				Where("msg_id > ? and msg_id < ? and msg_id not in ? and ( (chat_id = ? and sender = ? ) or (chat_id = ? and sender = ? ))",
					req.OldMsgID, req.LastMsgID, req.Exclude,
					c.UserID, req.ChatID, req.ChatID, c.UserID,
				).
				Find(&pushList)
		}
	}

	if dbResp.Error != nil {
		c.logger.Info("Sync Chat Info DB err", zap.Error(dbResp.Error))
		err = errors.New("服务器错误")
		return
	}

	resp.SyncID = req.SyncID

	for index, message := range pushList {
		//c.logger.Debug("推送数据", zap.Int("index", index), zap.Int64("msgid", message.MsgID))

		_ = index

		//if message.ChatID >  {
		//
		//}

		tmp := DBMessageToClientMessage(c.UserID, message)
		//message.Params

		//tmp.Params = message.Params
		//tmp.AtUser =

		resp.Messages = append(resp.Messages, tmp)
	}

	return
}

func (c *ClientConn) GetHistoryMsgApi(req *models.GetHistoryMsgReq) (resp *models.GetHistoryMsgResp, err error) {
	db := c.svr.db

	var pushList []*models.SingleMessage

	resp = new(models.GetHistoryMsgResp)

	var dbResp *gorm.DB
	if req.ChatID < 0 {
		// 群组的处理方式 , 只看chat id 相同即可
		if len(req.Exclude) > 0 {
			dbResp = db.Model(&models.SingleMessage{}).
				Where("msg_id < ?  and msg_id not in ? and   chat_id = ?  ",
					req.LastMsgID,
					req.Exclude,
					req.ChatID,
				).Order("msg_id desc").Limit(req.Limit).Offset(req.Offset).
				Find(&pushList)
		} else {
			dbResp = db.Model(&models.SingleMessage{}).
				Where("msg_id < ?  and   chat_id = ?  ",
					req.LastMsgID,
					req.ChatID,
				).Order("msg_id desc").Limit(req.Limit).Offset(req.Offset).
				Find(&pushList)
		}
	} else {
		// 个人的处理方式

		if len(req.Exclude) > 0 {
			dbResp = db.Model(&models.SingleMessage{}).
				Where("msg_id < ?   and msg_id not in ? and ( (chat_id = ? and sender = ? ) or (chat_id = ? and sender = ? ))",
					req.LastMsgID, req.Exclude,
					c.UserID, req.ChatID, req.ChatID, c.UserID,
				).Order("msg_id desc").
				Limit(req.Limit).
				Offset(req.Offset).
				Find(&pushList)
		} else {
			dbResp = db.Model(&models.SingleMessage{}).
				Where("msg_id < ?   and ( (chat_id = ? and sender = ? ) or (chat_id = ? and sender = ? ))",
					req.LastMsgID,
					c.UserID, req.ChatID, req.ChatID, c.UserID,
				).Order("msg_id desc").
				Limit(req.Limit).
				Offset(req.Offset).
				Find(&pushList)
		}

	}

	if dbResp.Error != nil {
		c.logger.Info("Sync Chat Info DB err", zap.Error(dbResp.Error))
		err = errors.New("服务器错误")
		return
	}

	for index, message := range pushList {
		//c.logger.Debug("推送数据", zap.Int("index", index), zap.Int64("msgid", message.MsgID))

		_ = index
		tmp := &models.SingleMessageDataType{}

		//if message.ChatID >  {
		//
		//}

		if message.ChatID < 0 {
			tmp.ChatID = message.ChatID
		} else {
			if message.ChatID == c.UserID {
				tmp.ChatID = message.Sender
			} else {
				tmp.ChatID = message.ChatID
			}
		}

		tmp.MsgID = message.MsgID
		tmp.CreatedAt = message.CreatedAt
		tmp.UpdatedAt = message.UpdatedAt
		tmp.Sender = message.Sender

		tmp.MsgType = message.MsgType
		tmp.MsgStatus = message.MsgStatus
		tmp.Body = message.Body
		tmp.Attach = message.Attach
		tmp.ReplyToMessageID = message.ReplyToMessageID
		tmp.ReplyInChatID = message.ReplyInChatID

		// 序列化 AtUser

		if message.AtUser != nil {
			tmpAtuserErr := json.Unmarshal(message.AtUser, &tmp.AtUser)
			//c.logger.Debug("json at user Unmarshal err", zap.Error(tmpAtuserErr))
			_ = tmpAtuserErr
		}

		if message.Params != nil {
			tmpParamsErr := json.Unmarshal(message.Params, &tmp.Params)
			_ = tmpParamsErr
			//c.logger.Debug("json Params Unmarshal err", zap.Error(tmpParamsErr))
		}

		//message.Params

		//tmp.Params = message.Params
		//tmp.AtUser =

		resp.Messages = append(resp.Messages, tmp)
	}

	return
}
